#pragma once 
#include <iostream>
#include <cstdint>
#include <sys/socket.h>
#include <netinet/in.h>
#include "Commn.hpp"
#include "Log.hpp"
#include <string>
#include <arpa/inet.h>
#include <functional>
#include "InetAddr.hpp"
#include "ThreadPool.hpp"
#include <cstring>

using namespace LogModule;
const uint16_t gport = 8888;
using func_t = std::function<std::string(std::string&)>;
using adduser_t = std::function<void(InetAddr&)>;
using deluser_t = std::function<void(InetAddr&)>;
using route_t = std::function<void(int fd,std::string& message)>;
using task_t = std::function<void()>;
using namespace MyThreadPool;

class Udp_server
{
public:
    Udp_server(uint16_t port=gport)
        :_port(port)
    {

    }
    void Init()
    {
        _socketfd = ::socket(AF_INET,SOCK_DGRAM,0); //获取文件描述符
        if (_socketfd < 0) 
        {
            Die(SOCKET_ERROR);
        }
        LOG(LogLevel::DEBUG) << "socket create success, fd is " << _socketfd;
        //进行绑定
        InetAddr local(_port); //只需要传入一个端口号即可。

        // local.sin_family = AF_INET; //本质也是无符号16位整数
        // local.sin_port = ::htons(_port); //主机序列转为网络序列
        // local.sin_addr.s_addr = INADDR_ANY; //s2位无符号整型
        // socklen_t len = sizeof(local);

        int n = ::bind(_socketfd,local.NetAddr(),local.Len());
        if (n < 0)
        {
            Die(BIND_ERROR);
        }
        LOG(LogLevel::DEBUG) << "bind create success";
    }

    void Register(adduser_t adduser,route_t route,deluser_t deluser)
    {
        _adduser = adduser;
        _route = route;
        _deluser = deluser;
    }
    
    void Start()
    {
        char buffer[1024];
        sockaddr_in peer; //对端消息
        socklen_t len = sizeof(peer); //一定要初始化!!!!
        while(true)
        {
            int n = ::recvfrom(_socketfd,buffer,sizeof(buffer)-1,0,CONV(&peer),&len);
            std::cout << n << std::endl;
            if (n > 0)
            {
                buffer[n] = 0;
                InetAddr Addr(peer);
                std::string message;

                if (strcmp(buffer,"QUIT") == 0)
                {
                    _deluser(Addr);
                    message = "我走了，你们聊!";
                }
                else 
                {
                    _adduser(Addr);
                    message = Addr.netaddr() + " #" + buffer;
                }

                LOG(LogLevel::INFO) << message;
                // task_t t = std::bind(Udp_server::_route,_socketfd,message);
	            task_t t = [=]() mutable{ //这里要传值传递，传引用传递的话可能会出现乱码!!!!!!!!!!!!!!!!!!!!!!!!
                    _route(_socketfd, message);
                };
                threadpool<task_t>::Getinstance()->Equeue(t);
                ////////////////////////////////////////////////////////////////////////
                // std::string client = "echo server says# ";
                // client += buffer;
                // //转换
                // // char Ip[64];
                // // ::inet_ntop(AF_INET,&(peer.sin_addr),Ip,64); //把网络ip地址转为点分十进制 192.132.168.10
                // // std::string ip = Ip;
                // // std::string port = std::to_string(ntohs(_port));
                // LOG(LogLevel::INFO) << Addr.IP() << ":" << Addr.Port() << "says# " << buffer;
                // ::sendto(_socketfd,client.c_str(),client.size(),0,CONV(&peer),len);
            }
        }
    }
    ~Udp_server()
    {}
private:
    int _socketfd;
    uint16_t _port;
    adduser_t _adduser;
    route_t _route;
    deluser_t _deluser;
};

